#ifndef POLYGON_H
#define POLYGON_H

#endif // POLYGON_H
#pragma once
#include <vector>
#include "rectangle.h"
#include <math.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <time.h>
using namespace std;

class pos {
public:
    int x;
    int y;
    bool operator ==(const pos& p) const {
        if (p.x == this->x&&p.y == this->y) {
            return true;
        }
        return false;
    }
    static double get_instance(pos point_1, pos point_2) {
        return pow(pow(point_1.x - point_2.x, 2) + pow(point_1.y - point_2.y, 2), 0.5);
    }
    pos(int x, int y) {
        this->x = x;
        this->y = y;
    }

    pos() {}
};

class polygon //计算拼接用的多边形类
{
public:
    //表示法1：顶点
    vector<pos> allVertrx;
    //表示法2：矩形拼接
    vector<rectangle> allRect;
    //装空白矩形（可填充）
    vector<rectangle> all_blank_Rect;
    string init_inf;
    polygon(const polygon& poly) {
        this->allVertrx.assign(poly.allVertrx.begin(), poly.allVertrx.end());
        this->allRect.assign(poly.allRect.begin(), poly.allRect.end());
        this->all_blank_Rect.assign(poly.all_blank_Rect.begin(), poly.all_blank_Rect.end());
        this->init_inf=poly.init_inf;
    }
    polygon &operator=(const polygon& poly) {
        this->allVertrx.assign(poly.allVertrx.begin(), poly.allVertrx.end());
        this->allRect.assign(poly.allRect.begin(), poly.allRect.end());
        this->all_blank_Rect.assign(poly.all_blank_Rect.begin(), poly.all_blank_Rect.end());
        this->init_inf=poly.init_inf;
        return *this;
    }
    bool operator ==(const polygon& p) const {
        if (p.allVertrx.size() != this->allVertrx.size()) {
            return false;
        }
        for (int i = 0; i < p.allVertrx.size(); i++) {
            if (find(this->allVertrx.begin(), this->allVertrx.end(), p.allVertrx[i]) == this->allVertrx.end()) {
                return false;
            }
        }
        return true;
    }
    polygon() {}
    polygon(const vector<pos>& temp_vertrx) {
        this->allVertrx.assign(temp_vertrx.begin(), temp_vertrx.end());
    }
    pos find_nextpos(pos start, pos point, vector<pos> Vertrxs, int& state) {
        for (auto iter = Vertrxs.begin(); iter != Vertrxs.end();) {        //从vector中删除指定的某一个元素
            if ((*iter) == start || (*iter) == point) {
                iter = Vertrxs.erase(iter);
            }
            else {
                iter++;
            }
        }
        for (pos temp : Vertrxs) {
            switch (state) {
            case -1:
                if (temp.x == point.x) {
                    state = 0;
                    return temp;
                }
                if (temp.y == point.y) {
                    state = 1;
                    return temp;
                }
                break;
            case 0:
                if (temp.y == point.y) {
                    state = 1;
                    return temp;
                }
                break;

            case 1:
                if (temp.x == point.x) {
                    state = 0;
                    return temp;
                }
                break;
            }

        }
        return pos(-1, -1);
    }

    void addVertrx(int x, int y) { this->allVertrx.push_back(pos(x, y)); }
    void toRepr2(int i = 0) //将多边形转换为矩形拼接
    {
        allRect = get_rectrangles();
    }
    //获取点重复次数
    int get_occurrences(pos target, const vector<pos>& pos_vec) {
        int times = 0;
        for (const pos& temp : pos_vec) {
            if (temp == target) {
                times++;
            }
        }
        return times;
    }
    //获取空白矩形（可填充矩形）
    void get_blank_Repr() {
        this->all_blank_Rect.clear();
        vector<vector<pos>> allrect_points;
        for (rectangle rect : allRect) {
            allrect_points.push_back(get_pos(rect));
        }
        vector<pos> blank_rec_points;
        for (int i = 0; i < allrect_points.size(); i++) {
            const vector<pos>& temp_rect = allrect_points[i];
            vector<pos> other_rect;
            for (int j = 0; j < allrect_points.size(); j++) {
                if (i == j) {
                    continue;
                }
                other_rect.insert(other_rect.end(), allrect_points[j].begin(), allrect_points[j].end());
            }
            for (int i = 0; i < temp_rect.size(); i++) {
                int times = get_occurrences(temp_rect[i], other_rect);
                if (times == 1) {
                    continue;
                }
                if (times == 2 || judge_if_online(temp_rect[i], other_rect)) {
                    if (find(blank_rec_points.begin(), blank_rec_points.end(), temp_rect[i]) == blank_rec_points.end())
                        blank_rec_points.push_back(temp_rect[i]);
                }
            }
        }
        vector<pos> allpoints;
        for (vector<pos> temp_rect_points : allrect_points) {
            allpoints.insert(allpoints.end(), temp_rect_points.begin(), temp_rect_points.end());
        }
        const vector<pos>& four_vertices = get_pos(get_rectangle(allpoints));
        vector<pos> blank_points;
        for (pos temp : four_vertices) {
            if (find(allpoints.begin(), allpoints.end(), temp) == allpoints.end()) {
                blank_points.push_back(temp);
            }
        }

        if (blank_rec_points.size() == 1) {
            this->all_blank_Rect.push_back(get_rectangle({ blank_rec_points[0],blank_points[0] }));
        }
        else {
            if (blank_points.size() == 1) {
                for (pos temp : blank_rec_points) {
                    this->all_blank_Rect.push_back(get_rectangle({ temp,blank_points[0] }));
                }
            }
            else {
                double sum_equ = pos::get_instance(blank_points[0], blank_rec_points[0]) + pos::get_instance(blank_points[1], blank_rec_points[1]);
                double sum_n_equ = pos::get_instance(blank_points[0], blank_rec_points[1]) + pos::get_instance(blank_points[1], blank_rec_points[0]);
                if (sum_equ < sum_n_equ) {
                    this->all_blank_Rect.push_back(get_rectangle({ blank_points[0],blank_rec_points[0] }));
                    this->all_blank_Rect.push_back(get_rectangle({ blank_points[1],blank_rec_points[1] }));
                }
                else {
                    this->all_blank_Rect.push_back(get_rectangle({ blank_points[0],blank_rec_points[1] }));
                    this->all_blank_Rect.push_back(get_rectangle({ blank_points[1],blank_rec_points[0] }));
                }
            }
        }



    }
    //获取外接矩形
    static rectangle get_rectangle(const vector<pos>& points) {
        int x_min, x_max, y_min, y_max;
        for (int i = 0; i < points.size(); i++) {
            if (i == 0) {
                x_min = points[i].x;
                x_max = points[i].x;
                y_min = points[i].y;
                y_max = points[i].y;
            }
            else {
                x_min = points[i].x < x_min ? points[i].x : x_min;
                x_max = points[i].x > x_max ? points[i].x : x_max;
                y_min = points[i].y < y_min ? points[i].y : y_min;
                y_max = points[i].y > y_max ? points[i].y : y_max;
            }
        }
        return rectangle(x_min, y_min, x_max, y_max);
    }
    //获取矩形的四个点
    vector<pos> get_pos(const rectangle& rect) {
        return { pos(rect.x1,rect.y1),pos(rect.x2,rect.y1),pos(rect.x2,rect.y2),pos(rect.x1,rect.y2) };
    }
    bool do_judge(const pos& point, const vector<pos>& Vertrx) {
        if (find(Vertrx.begin(), Vertrx.end(), point) != Vertrx.end()) {
            return true;
        }
        return judge_if_online(point, Vertrx);
    }
    //查看点是否在多边形的边上呢
    bool judge_if_online(const pos& point, const vector<pos>& Vertrx) {
        int x_equ_min, x_equ_max, y_equ_min, y_equ_max;
        x_equ_min = Vertrx[0].y;
        x_equ_max = Vertrx[0].y;
        y_equ_min = Vertrx[0].x;
        y_equ_max = Vertrx[0].x;
        for (pos i : Vertrx) {
            if (i.x == point.x) {
                x_equ_min = i.y < x_equ_min ? i.y : x_equ_min;
                x_equ_max = i.y > x_equ_max ? i.y : x_equ_max;
            }
            if (i.y == point.y) {
                y_equ_min = i.x < y_equ_min ? i.x : y_equ_min;
                y_equ_max = i.x > y_equ_max ? i.x : y_equ_max;
            }
        }
        if (x_equ_max > point.y&&x_equ_min < point.y) {
            return true;
        }
        if (y_equ_max > point.x&&y_equ_min < point.x) {
            return true;
        }
        return false;
    }
    bool judge_in_polygon(const pos& start, const pos& temp, const vector<pos>& Vertrx) {
        pos point_1 = pos(start.x, temp.y);
        pos point_2 = pos(temp.x, start.y);
        return do_judge(point_1, Vertrx) && do_judge(point_2, Vertrx);

    }
    static int get_rec_area_sum(const polygon& poly) {
        int area_sum = 0;
        for (const rectangle& temp_rec : poly.allRect) {
            area_sum += temp_rec.area;
        }
        return area_sum;
    }
    //删除已切完的矩形
    void cut_rectangle(vector<pos>& store, const vector<pos>& points) {
        for (pos point : points) {
            auto iter = find(store.begin(), store.end(), point);
            if (iter == store.end()) {
                store.push_back(point);
            }
            else {
                store.erase(iter);
            }
        }
    }
    vector<rectangle> get_rectrangles() {
        static int sand = 0;
        int count = 0;
        while (true) {
            if (count != 0) {
                srand(time(0) + sand);
                random_shuffle(this->allVertrx.begin(), this->allVertrx.end());
            }
            count++;
            sand++;
            for (int i = 0; i < allVertrx.size(); i++) {
                vector<rectangle> result;
                vector<pos> store = allVertrx;
                pos nextpos = pos();
                pos start = allVertrx[i];
                pos temp = allVertrx[i];
                while (true) {
                    bool flag = false;
                    if (store.size() > 4) {
                        int state = -1;
                        for (int i = 0; i < 2; i++) {
                            nextpos = find_nextpos(start, temp, store, state);
                            if (nextpos.x != -1) {
                                temp = nextpos;
                            }
                            else {
                                flag = true;
                                break;
                            }
                        }
                        if (flag == true) {
                            break;
                        }
                        if (judge_in_polygon(start, temp, store)) {
                            result.push_back(rectangle(min(start.x, temp.x),
                                min(start.y, temp.y),
                                max(start.x, temp.x),
                                max(start.y, temp.y)));
                            cut_rectangle(store, { start,temp,
                                                 pos(start.x,temp.y),
                                                 pos(temp.x,start.y) });

                            start = store[0];
                            temp = store[0];
                        }
                        else {
                            break;
                        }

                    }
                    else {
                        result.push_back(rectangle(min(min(store[0].x, store[1].x), min(store[2].x, store[3].x)),
                            min(min(store[0].y, store[1].y), min(store[2].y, store[3].y)),
                            max(max(store[0].x, store[1].x), max(store[2].x, store[3].x)),
                            max(max(store[0].y, store[1].y), max(store[2].y, store[3].y))));
                        return result;
                    }
                }

            }
        }
    }
    //移动图形位置
    static void std_pos_vec(vector<pos>& pos_vec, int std_x, int std_y)
    {
        rectangle rec_temp = get_rectangle(pos_vec);
        int x_mov = std_x - rec_temp.x1;
        int y_mov = std_y - rec_temp.y1;
        for (pos& temp : pos_vec) {
            temp.x += x_mov;
            temp.y += y_mov;
        }
    }
    static void std_pos_vec(vector<pos>& pos_vec, int std_x, int std_y, int rec_x, int rec_y)
    {
        int x_mov = std_x - rec_x;
        int y_mov = std_y - rec_y;
        for (pos& temp : pos_vec) {
            temp.x += x_mov;
            temp.y += y_mov;
        }
    }
};


